<?php

namespace GroupBuying;

use C\L\WebUserController;
use C\M\GroupBuyingGoods;
use C\M\GroupBuyingOrder;
use C\M\GroupBuyingUserOrder;

const COMMISSION_TYPE_ENUM = [
  'A' => '每日返佣，到期返本',
  'B' => '每日复利返佣，到期返本',
  'C' => '一次性返佣返本',
];

class OrderController extends WebUserController
{
    /**
     * 列表、搜索接口
     **/
    public function indexAction()
    {
        $currentPage = $this->request->getQuery('page', 'int', 1);
        $perPage     = $this->request->getQuery('per_page', 'int', 20);
        $sn          = $this->request->getQuery('sn', 'string', null);
        $state       = $this->request->getQuery('state', 'string', null);

        $columns = ['id', 'sn', 'state', 'other_info', 'addtime'];
        $conditions = '1 = 1';
        $bind = [];

        if ($sn) {
            $conditions .= ' and sn like :sn:';
            $bind['sn'] = '%' . $sn . '%';
        }

        if ($state) {
            $conditions .= ' and state = :state:';
            $bind['state'] = $state;
        }

        $params =  [
            'conditions' => $conditions,
            'bind'       => $bind,
            'columns'    => $columns,
            'order'      => 'id DESC',
        ];
        $pagination = $this->paginate(GroupBuyingOrder::class, $currentPage, $perPage, $params);

        $offset = ($currentPage - 1) * $perPage;
        $params['limit'] = [$perPage, $offset];
        $items = GroupBuyingOrder::find($params);

        // 整理结构
        $items = array_map(
            function ($item) {
                ['user' => $user, 'goods' => $goods] = json_decode($item['other_info'], true);

                $item['user'] = $user;
                $item['goods'] = $goods;

                unset($item['other_info']);
                return $item;
            },
            $items->toArray()
        );

        $this->success(compact('pagination', 'items'));
    }

  /**
   * 详情接口
   **/
    public function showAction()
    {
        $id = $this->request->getQuery('id', 'int', 0);

        $order = GroupBuyingOrder::findFirst([
            'conditions' => 'id = :id: AND state = :state:',
            'bind' => [
                'id'    => $id,
                'state' => 'processing',
            ],
        ]);
        if (!$order) {
            return $this->error('未查询到该团购信息');
        }

        [
            'goods'        => $goods,
            'group_buying' => $groupBuying,
        ] = json_decode($order->other_info, true);

        $sum = GroupBuyingUserOrder::sum([
            'group_buying_order_id = ' . $order->id,
            'column' => 'quantity',
        ]);

        $currentJoinCount = $sum + $order->quantity;
        $order = [
            'sn'                 => $order->sn,
            'current_join_count' => $currentJoinCount ?? 0,
        ];

        $result = [
            'order'        => $order,
            'group_buying' => $groupBuying,
            'goods'        => $goods,
        ];

        return $this->success($result);
    }

  /**
   * 确认接口
   **/
    public function membersAction()
    {
        $id = $this->request->getQuery('id', 'int', 0);

        $order = GroupBuyingOrder::findFirst($id);
        if (!$order) {
            return $this->error('未查询到该团购信息');
        }

        $userOrders = GroupBuyingUserOrder::find([
            'group_buying_order_id = ' . $id,
            'columns' => ['user_id', 'other_info', 'addtime'],
            'limit'   => 50,
        ]);

        $result = array_map(function ($item) {
            $otherInfo = json_decode($item['other_info'], true);
            return [
                'mobile'    => $otherInfo['member']['mobile'],
                'joined_at' => $item['addtime'],
            ];
        }, $userOrders->toArray());

        $orderOtherInfo = json_decode($order->other_info, true) ?? [];
        array_push($result, [
            'mobile'    => $orderOtherInfo['user']['mobile'],
            'joined_at' => $order->addtime,
        ]);

        $result = array_map(function ($item) {
            $front = substr($item['mobile'], 0, 3);
            $end   = substr($item['mobile'], -4, 4);
            $item['mobile'] = $front . '****' . $end;
            return $item;
        }, $result);

        $this->success($result);
    }

    /**
     * 预确认接口
     **/
    public function checkoutAction()
    {
        $this->checkAuth();
        $this->checkPaymentPassword();

        $userId          = $this->uid;
        $goodsId         = $this->request->getPost('goods_id', 'int', 0);
        $couponId        = $this->request->getPost('coupon_id', 'int', 0);
        $quantity        = $this->request->getPost('quantity', 'int', 0);

        $goods = GroupBuyingGoods::findFirst($goodsId);
        if (!$goods) {
            return $this->error('未找到对应商品');
        }

        if ($goods->status != 'on_sale') {
            return $this->error('该商品不能下单');
        }

        $amount = $quantity * $goods->price;

        $coupons = $this->getCoupons($userId, $amount);

        $selectedCoupon = $this->getCoupon($coupons, $couponId);

        $paymentAmount = $amount - ($selectedCoupon['value'] ?? 0) / 100;

        $commission = $this->getCommission($userId, $amount, $goods);

        $result = [
            'amount'           => $amount,
            'payment_amount'   => $paymentAmount,

            'commission'       => $commission,

            'selected_coupon'  => $selectedCoupon,
            'coupons'          => $coupons,

            'goods' => [
                'title'     => $goods->title,
                'price'     => $goods->price,
                'thumbnail' => $goods->thumbnail,
            ],
        ];

        $this->success($result);
    }

    /**
     * 确认接口
     **/
    public function confirmAction()
    {
        $this->checkAuth();
        $this->checkPaymentPassword();

        $userId          = $this->uid;
        $goodsId         = $this->request->getPost('goods_id', 'int', 0);
        $quantity        = $this->request->getPost('quantity', 'int', 0);
        $paymentPassword = $this->request->getPost('payment_password', 'string', null);
        $couponId        = $this->request->getPost('coupon_id', 'int', null);

        if (!$this->s_user->checkPayPwd($userId, $paymentPassword)) {
            return $this->error('支付密码错误');
        }

        try {
            $this->s_group_buying_order->confirm($userId, $goodsId, $quantity, $couponId);
            $this->success();
        } catch (\Exception $e) {
            $this->error($e->getMessage());
        }
    }

    /**
     * 合同接口
     **/
    public function contractAction()
    {
        $id = $this->request->getQuery('id', 'int', 0);

        $order = GroupBuyingOrder::findFirst([
            'id = :id: AND user_id = :user_id:',
            'bind' => ['id' => $id, 'user_id' => $this->uid],
        ]);
        if (!$order) {
            return $this->error('该订单不存在');
        }

        $contract = $order->getContract();
        if (!$contract) {
            return $this->error('合同功能正在维护');
        }

        $user = $order->user;
        $commissionInfo = $order->getCommissionInfo();
        $rate = bcadd($commissionInfo['rate'], $commissionInfo['vip_rate'], 2);

        $comissionParams = ['cid' => $order->id, 'uid' => $user->uid];
        $returnAmount = bcadd(
            $this->s_itemaprlist->getSum('apr_money', $comissionParams),
            $this->s_itemaprlist->getSum('money', $comissionParams),
            2
        );
        $comissionStartDate = date(
            'Y-m-d',
            $this->s_itemaprlist->getMin('back_time', $comissionParams)
        );
        $comissionEndDate = date(
            'Y-m-d',
            $this->s_itemaprlist->getMax('back_time', $comissionParams)
        );

        $commissions = $this->s_itemaprlist->getCommissionFromOrder($order);
        $profit = array_reduce($commissions, function ($result, $item) {
            $result += ($item['apr_money'] ?? 0);
            return $result;
        }, 0);

        $goods = $order->groupBuyingGoods;
        $commissionType = $commissionInfo['type'];

        $detail = [
            'goods_name'            => $goods->title,
            'user_name'             => $user->name,
            'user_idcard'           => $user->idcard,
            'order_sn'              => $order->sn,
            'order_amount'          => $order->amount,
            'order_created_at'      => date('Y年m月d日', $order->addtime),
            'commission_type'       => COMMISSION_TYPE_ENUM[$commissionType],
            'commission_period'     => $commissionInfo['period'],
            'commission_rate'       => $rate,
            'commission_start_date' => $comissionStartDate,
            'commission_end_date'   => $comissionEndDate,
            'return_amount'         => $returnAmount,
        ];

        $data = compact('detail', 'contract');

        $this->success($data);
    }

    private function getCoupons($userId, $amount)
    {
        $coupons = $this->s_coupon_receive->availableCoupons($userId, $amount);

        return array_map(function ($item) {
            return [
                'id'        => $item['id'],
                'condition' => $item['use_condition_msg'],
                'startAt'   => $item['stime'],
                'endAt'     => $item['etime'],
                'value'     => $item['coupon_value'] * 100,
                'valueDesc' => $item['coupon_value'],
                'name'      => '代金券',
                'unitDesc'  => '元',
            ];
        }, $coupons);
    }

    private function getCoupon($coupons, $couponId = null)
    {
        /**
         * couponId = -1,   不使用代金券
         * couponId = null, 获取金额最大的代金券
         * couponId = :id:, 获取指定代金券
         **/
        if ($couponId == -1) {
            return null;
        }

        if ($couponId == null) {
            return array_reduce($coupons, function ($result, $item) {
                return $item['value'] > ($result['value'] ?? 0) ? $item : $result;
            }, null);
        }

        return array_reduce($coupons, function ($result, $item) use ($couponId) {
            return $item['id'] == $couponId ? $item : $result;
        }, null);
    }

    private function getCommission($userId, $amount, $goods)
    {
        [
            'commission_type'      => $type,
            'commission_rate'      => $rate,
            'commission_period'    => $period,
            'commission_vip_bonus' => $vipBonus,
        ] = json_decode($goods->other_info, true);

        $vipRate = 0;
        if ($vipBonus === 'enabled') {
            $level = $this->di['s_level']->getLevel($userId);
            $vipRate = $level['apr'] ?? 0;
        }

        $rate += $vipRate;
        $profit = 0;
        switch ($type) {
            case 'A':
            case 'C':
                $profit = bcmul($rate / 100 * $amount, $period, 2);
                break;
            case 'B':
                $total = $amount * ($rate / 100 + 1) ** $period;
                $profit = bcsub($total, $amount, 2);
                break;
        }

        $result = [
            'type'      => COMMISSION_TYPE_ENUM[$type],
            'period'    => $period,
            'principal' => $amount,
            'profit'    => $profit,
            'vip_bonus' => $vipRate,
        ];

        return $result;
    }
}
